package main

import (
	"fmt"
	"unicode/utf8"
)

/*
*
值类型：打印地址，直接用取值符(&)打印。
引用类型：打印地址，%p 打印
字符串底层是byte数组
rune 是 int32别名，一个rune有4字节空间，用于表示 每个 unicode 码点
*/
func main() {
	basic()
	s := "Yes最棒"
	//s := "Hello world 0!!!"
	fmt.Println("====")
	// 将字符串强制转换为 []byte字节序列后,每次迭代会直接输出unicode码点对应的rune类型值(一般不会产生运行时开销)
	// rune 是 int32类型别名
	//// Yes 对应三个unicode:(0 59) (1 65) (2 73)//前一个数字表示转换为unicode码点数组后的索引
	//// 最 由三个unicode 构成：(3 e6) (4 9c) (5 80)//三个unicode共同组成一个 rune数组 构成了最这个字符
	//// 棒 由三个unicode 构成：(6 e6) (7 a3) (8 92)
	for i, ch := range []byte(s) {
		fmt.Printf("(%d %x) ", i, ch)
	}

	fmt.Println()

	// for range 会将每个字符进行UTF8 解码
	// 再对解码后的字符转换为Unicode(英文用一个unicode表示，汉字用3个unicode表示)
	// 最后将每个字符对应的unicode,分别存入一个4字节的rune中
	for i, ch := range s { // ch is rune，记录每个rune在UTF8底层字符中的开始位置
		fmt.Printf("(%d %v)", i, ch)
	}
	fmt.Println()
	fmt.Println(utf8.RuneCountInString(s)) //字符串rune序列长度
	fmt.Println(len(s))                    // UTF8解码后的字节长度

	bytes := []byte(s)
	for len(bytes) > 0 {
		// DecodeRune unpack the first UTF8 encoding in p
		// and return rune and its width in bytes
		ch, size := utf8.DecodeRune(bytes) //解码字节数组到rune中，返回rune和这个rune的宽度
		bytes = bytes[size:]
		fmt.Printf("%c ", ch)
	}

	// 会为每个ch 新分配一块4字节内存，将每个字符存在新的rune地址空间
	// 与直接遍历字符串`s`不同在于，编码解码后会为每个ch分配一块新的rune空间
	// []byte(s)，是对字符串s底层的解释，而[]rune(s)会分配新空间(Decode包括字符UTF8转Unicode，然后Unicode转换为rune，此处的rune存于新开辟的内存)
	// 	for i, ch := range []rune(s) {
	//
	// 	}
}

func basic() {
	s1 := "eggo世界"
	fmt.Printf("%c\n", s1[2]) // 字符串底层是只读的字节数组，可以通过索引获取值
	fmt.Printf("s1: addr=%v,value=%v \n", &s1, s1)
	fmt.Printf("s1: addr=%p\n", &s1)

	bs := ([]byte)(s1) // 重新分配内存，并拷贝s1的内容到[]byte切片中
	bs[2] = 'o'
	fmt.Printf("%c\n", bs[2])
	// [101 103 111 111 228 184 150 231 149 140]，228和184和150共同组成了世，231和149和140 共同组成了界
	// 世(unicode 字符编号 19990) 1110<0100> 10<111000> 10<010110>
	//0100 1110 0001 0110 --> 19990
	fmt.Printf("bs: value=%v \n", bs)
	fmt.Printf("bs: addr=%p \n", bs)
	fmt.Printf("s1: addr=%v,value=%v \n", &s1, s1)
}
